<!--
 * @Descripttion: scContextmenu组件
 * @version: 1.0
 * @Author: sakuya
 * @Date: 2021年7月23日09:25:57
 * @LastEditors:
 * @LastEditTime:
 * @other: 代码完全开源，欢迎参考，也欢迎PR
-->

<template>
	<transition name="el-zoom-in-top">
		<div v-if="visible" ref="contextmenu" class="sc-contextmenu" :style="{left:left+'px',top:top+'px'}"
			@contextmenu.prevent="fun">
			<ul class="sc-contextmenu__menu">
				<slot></slot>
			</ul>
		</div>
	</transition>
</template>

<!-- Composition API -->
<script>
	import { provide, toRefs, ref, reactive, watch } from 'vue';

	export default {
		name: "scContextmenu",
		components: {
		},
		setup(props, context) {
			const data = reactive({
				visible: false,
				top: 0,
				left: 0
			});

			function menuClick(command) {
				closeMenu()
				context.emit('command', command)
			}

			function openMenu(e) {
				e.preventDefault()
				data.visible = true
				data.left = e.clientX + 1
				data.top = e.clientY + 1

				// 将回调延迟到下次 DOM 更新循环之后执行
				var _this = this;
				this.$nextTick(() => {
					var ex = e.clientX + 1
					var ey = e.clientY + 1
					var innerWidth = window.innerWidth
					var innerHeight = window.innerHeight
					var menuHeight = this.$refs.contextmenu.offsetHeight
					var menuWidth = this.$refs.contextmenu.offsetWidth

					console.log(this, _this, data);

					//位置修正公示
					//left = (当前点击X + 菜单宽度 > 可视区域宽度 ? 可视区域宽度 - 菜单宽度 : 当前点击X)
					//top = (当前点击Y + 菜单高度 > 可视区域高度 ? 当前点击Y - 菜单高度 : 当前点击Y)
					data.left = ex + menuWidth > innerWidth ? innerWidth - menuWidth : ex
					data.top = ey + menuHeight > innerHeight ? ey - menuHeight : ey
				})
				context.emit('visibleChange', true)
			}

			function closeMenu() {
				data.visible = false;
				context.emit('visibleChange', false)
			}

			function fun() {
				return false;
			}

			provide("menuClick", {
				menuClick: menuClick
			})

			const contextmenu = ref(null);

			watch(() => data.visible, () => {
				var cm = function (e) {
					let sp = contextmenu.value;
					console.log(contextmenu.value, sp.contains);
					if (sp && !sp.contains(e.target)) {
						closeMenu()
					}
				}

				if (data.visible) {
					document.body.addEventListener('click', e => cm(e))
				} else {
					document.body.removeEventListener('click', e => cm(e))
				}
			})

			return {
				...toRefs(data),
				openMenu,
				fun,
				contextmenu
			}
		}
	}
</script>

<!-- Options API -->
<!-- <script>
	export default {
		provide() {
			return {
				menuClick: this.menuClick
			}
		},
		data() {
			return {
				visible: false,
				top: 0,
				left: 0
			}
		},
		watch: {
			visible(value) {
				var _this = this;
				var cm = function (e) {
					let sp = _this.$refs.contextmenu
					if (sp && !sp.contains(e.target)) {
						_this.closeMenu()
					}
				}
				if (value) {
					document.body.addEventListener('click', e => cm(e))
				} else {
					document.body.removeEventListener('click', e => cm(e))
				}
			}
		},
		mounted() {

		},
		methods: {
			menuClick(command) {
				this.closeMenu()
				this.$emit('command', command)
			},
			openMenu(e) {
				e.preventDefault()
				this.visible = true
				this.left = e.clientX + 1
				this.top = e.clientY + 1

				// 将回调延迟到下次 DOM 更新循环之后执行
				this.$nextTick(() => {
					var ex = e.clientX + 1
					var ey = e.clientY + 1
					var innerWidth = window.innerWidth
					var innerHeight = window.innerHeight
					var menuHeight = this.$refs.contextmenu.offsetHeight
					var menuWidth = this.$refs.contextmenu.offsetWidth
					//位置修正公示
					//left = (当前点击X + 菜单宽度 > 可视区域宽度 ? 可视区域宽度 - 菜单宽度 : 当前点击X)
					//top = (当前点击Y + 菜单高度 > 可视区域高度 ? 当前点击Y - 菜单高度 : 当前点击Y)
					this.left = ex + menuWidth > innerWidth ? innerWidth - menuWidth : ex
					this.top = ey + menuHeight > innerHeight ? ey - menuHeight : ey
				})
				this.$emit('visibleChange', true)
			},
			closeMenu() {
				this.visible = false;
				this.$emit('visibleChange', false)
			},
			fun() {
				return false;
			}
		}
	}
</script> -->

<style>
	.sc-contextmenu {
		position: fixed;
		/* 绝对定位 */
		z-index: 3000;
		/* 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。 */
	}

	.sc-contextmenu__menu {
		display: inline-block;
		/* 行内块元素。 */
		min-width: 120px;
		border: 1px solid #e4e7ed;
		background: #fff;
		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
		z-index: 3000;
		/* 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。 */
		list-style-type: none;
		/* 无标记。 */
		padding: 10px 0;
	}

	.sc-contextmenu__menu>hr {
		/* 分割线 */
		margin: 5px 0;
		border: none;
		height: 1px;
		font-size: 0px;
		background-color: #ebeef5;
	}

	.sc-contextmenu__menu>li {
		margin: 0;
		cursor: pointer;
		/* 鼠标样式 */
		line-height: 30px;
		/* 设置行间的距离（行高）。 */
		padding: 0 17px 0 10px;
		color: #606266;
		display: flex;
		/* 弹性布局 */
		justify-content: space-between;
		/* 两端对齐 */
		white-space: nowrap;
		/* 规定段落中的文本不进行换行 */
		text-decoration: none;
		/* 没有文本装饰 下划线*/
		position: relative;
		/* 相对定位 */
	}

	.sc-contextmenu__menu>li:hover {
		/* 鼠标浮动样式 */
		background-color: #ecf5ff;
		color: #66b1ff;
	}

	.sc-contextmenu__menu>li.disabled {
		/* 禁用样式 */
		cursor: not-allowed;
		color: #bbb;
		background: transparent;
	}

	.sc-contextmenu__icon {
		/* 图标样式 */
		display: inline-block;
		width: 14px;
		font-size: 14px;
		margin-right: 10px;
	}

	.sc-contextmenu__suffix {
		/* 后缀 */
		margin-left: 40px;
		color: #999;
	}

	.sc-contextmenu__menu li ul {
		position: absolute;
		top: 0px;
		left: 100%;
		display: none;
		margin: -11px 100;
	}
</style>